#include "gd32h7xx.h"
#include <stdio.h>
#include "gd32h759i_eval.h"
#include "systick.h"
#include "string.h"
 
// 64字节支持CANFD最大数据长度
#define  BUFFER_SIZE    64U
#define  COMM_STOP_DELAY 2000U  // 通信停止判断阈值(ms)
 
uint8_t tx_data[BUFFER_SIZE];
uint8_t rx_data[BUFFER_SIZE];
 
can_mailbox_descriptor_struct transmit_message;
can_mailbox_descriptor_struct receive_message;
FlagStatus can1_receive_flag = RESET;  // 全局接收标志
 
// 通信统计变量
volatile uint32_t systick_counter = 0;  // 毫秒计数器
uint32_t start_time = 0;                // 通信开始时间(ms)
uint32_t total_frames = 0;              // 总通信帧数
uint32_t last_second_frames = 0;        // 上一秒内的帧数
uint32_t last_second_time = 0;          // 上一次秒统计时间(ms)
uint32_t current_fps = 0;               // 当前帧率(帧/秒)
uint32_t max_fps = 0;                   // 最大帧率
uint32_t last_comm_time = 0;            // 最后一次通信时间(ms)
FlagStatus is_communicating = RESET;    // 通信状态标志
 
// 函数声明
void can_gpio_config(void);
void bsp_board_config(void);
void canfd_config(void);
void communication_check(void);
void cache_enable(void);
uint32_t get_current_time(void);
void check_comm_stop(void);
 
int main(void)
{
    can_struct_para_init(CAN_MDSC_STRUCT, &transmit_message);
    can_struct_para_init(CAN_MDSC_STRUCT, &receive_message);
 
    cache_enable();
    systick_config();  // 配置为1ms中断
    bsp_board_config();
    can_gpio_config();
    canfd_config();
 
    printf("CAN1 CANFD通信测试就绪！\r\n");
    printf("等待数据通信...\r\n");
 
    // 初始化发送消息结构
    transmit_message.rtr = 0U;                  // 数据帧
    transmit_message.ide = 0U;                  // 标准帧
    transmit_message.code = CAN_MB_TX_STATUS_DATA;
    transmit_message.brs = 1U;                  // 启用波特率切换
    transmit_message.fdf = 1U;                  // 启用CANFD模式
    transmit_message.prio = 0U;
    transmit_message.data_bytes = BUFFER_SIZE;  // 64字节数据
    transmit_message.data = (uint32_t *)(tx_data);
    transmit_message.id = 0x55U;                // 标准ID
 
    // 初始化接收消息结构
    receive_message.rtr = 0U;
    receive_message.ide = 0U;
    receive_message.code = CAN_MB_RX_STATUS_EMPTY;
    receive_message.id = 0x55U;
    receive_message.data = (uint32_t *)(rx_data);
    can_mailbox_config(CAN1, 0U, &receive_message);
 
    while(1) {
        communication_check();
        check_comm_stop();  // 检查是否停止通信
    }
}
 
// 获取当前时间(ms)
uint32_t get_current_time(void)
{
    return systick_counter;
}
 
// 检查通信是否停止
void check_comm_stop(void)
{
    if(is_communicating == SET) {
        uint32_t current_time = get_current_time();
        // 判断是否超过2秒无通信
        if((current_time - last_comm_time) >= COMM_STOP_DELAY) {
            uint32_t total_time = current_time - start_time;  // 总时间(ms)
            
            // 打印统计结果
            printf("\r\n===== 通信结束统计 =====");
            printf("\r\n总通信时间: %d ms (%.2f 秒)", 
                   total_time, total_time / 1000.0f);
            printf("\r\n总通信帧数: %d 帧", total_frames);
            printf("\r\n最大帧率: %d 帧/秒", max_fps);
            printf("\r\n========================\r\n");
            printf("等待下次通信...\r\n");
 
            // 重置统计变量
            is_communicating = RESET;
            total_frames = 0;
            max_fps = 0;
            start_time = 0;
            last_second_frames = 0;
            last_second_time = 0;
        }
    }
}
 
void can_gpio_config(void)
{
    rcu_can_clock_config(IDX_CAN1, RCU_CANSRC_APB2);
    rcu_periph_clock_enable(RCU_CAN1);
    rcu_periph_clock_enable(RCU_GPIOB);
 
    // 配置CAN1_RX (PB5)
    gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_5);
    gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_5);
    gpio_af_set(GPIOB, GPIO_AF_9, GPIO_PIN_5);
    
    // 配置CAN1_TX (PB13)
    gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_13);
    gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_13);
    gpio_af_set(GPIOB, GPIO_AF_9, GPIO_PIN_13);
}
 
void bsp_board_config(void)
{
    gd_eval_com_init(EVAL_COM);
    gd_eval_led_init(LED2);
    gd_eval_led_off(LED2);
}
 
void canfd_config(void)
{
    can_parameter_struct can_parameter;
    can_fd_parameter_struct can_fd_param;
 
    can_deinit(CAN1);
    
    // 初始化CAN参数结构体
    can_struct_para_init(CAN_INIT_STRUCT, &can_parameter);
    
    // 基本CAN参数配置
    can_parameter.internal_counter_source = CAN_TIMER_SOURCE_BIT_CLOCK;
    can_parameter.self_reception = DISABLE;
    can_parameter.mb_tx_order = CAN_TX_HIGH_PRIORITY_MB_FIRST;
    can_parameter.mb_tx_abort_enable = ENABLE;
    can_parameter.local_priority_enable = DISABLE;
    can_parameter.mb_rx_ide_rtr_type = CAN_IDE_RTR_FILTERED;
    can_parameter.mb_remote_frame = CAN_STORE_REMOTE_REQUEST_FRAME;
    can_parameter.rx_private_filter_queue_enable = DISABLE;
    can_parameter.edge_filter_enable = DISABLE;
    can_parameter.protocol_exception_enable = DISABLE;
    can_parameter.rx_filter_order = CAN_RX_FILTER_ORDER_MAILBOX_FIRST;
    can_parameter.memory_size = CAN_MEMSIZE_32_UNIT;
    can_parameter.mb_public_filter = 0U;
 
    // 仲裁段波特率配置 (1Mbps)
    can_parameter.resync_jump_width = 1U;
    can_parameter.prop_time_segment = 2U;
    can_parameter.time_segment_1 = 5U;
    can_parameter.time_segment_2 = 2U;
    can_parameter.prescaler = 30U;  
 
    // 初始化CAN控制器
    can_init(CAN1, &can_parameter);
    
    // 初始化CANFD参数结构体
    can_struct_para_init(CAN_FD_INIT_STRUCT, &can_fd_param);
    
    // CANFD参数配置
    can_fd_param.iso_can_fd_enable = ENABLE;              // 启用ISO CANFD
    can_fd_param.bitrate_switch_enable = ENABLE;          // 启用波特率切换
    can_fd_param.mailbox_data_size = CAN_MAILBOX_DATA_SIZE_64_BYTES; // 64字节数据
    can_fd_param.tdc_enable = DISABLE;                    // 禁用发送延迟补偿
    can_fd_param.tdc_offset = 0U;
    
    // 数据段波特率配置 (5Mbps)
    can_fd_param.resync_jump_width = 1U;
    can_fd_param.prop_time_segment = 2U;
    can_fd_param.time_segment_1 = 5U;
    can_fd_param.time_segment_2 = 2U;
    can_fd_param.prescaler = 6U;  
    
    // 配置CANFD
    can_fd_config(CAN1, &can_fd_param);
 
    // 配置中断
    nvic_irq_enable(CAN1_Message_IRQn, 0U, 0U);
    can_interrupt_enable(CAN1, CAN_INT_MB0);  // 使能邮箱0中断
 
    // 进入正常模式（非回环模式）
    can_operation_mode_enter(CAN1, CAN_NORMAL_MODE);
}
 
void communication_check(void)
{
    if(SET == can1_receive_flag) {
        can1_receive_flag = RESET;
        uint32_t current_time = get_current_time();
 
        // 读取接收的数据
        can_mailbox_receive_data_read(CAN1, 0U, &receive_message);
        
        // 首次通信初始化
        if(is_communicating == RESET) {
            is_communicating = SET;
            start_time = current_time;
            last_second_time = current_time;
            last_second_frames = 0;
            max_fps = 0;
            printf("\r\n===== 开始通信 =====");
        }
 
        // 更新通信时间和帧数
        last_comm_time = current_time;
        total_frames++;
        last_second_frames++;
 
        // 计算每秒帧率（每1秒更新一次）
        if((current_time - last_second_time) >= 1000U) {
            current_fps = last_second_frames;
            // 更新最大帧率
            if(current_fps > max_fps) {
                max_fps = current_fps;
            }
            // 打印实时帧率
            printf("\r\n当前帧率: %d 帧/秒 (累计: %d 帧)", current_fps, total_frames);
            
            // 重置秒统计
            last_second_time = current_time;
            last_second_frames = 0;
        }
 
        // 回发数据处理
        memcpy(tx_data, rx_data, receive_message.data_bytes);
        transmit_message.data_bytes = receive_message.data_bytes;
        can_mailbox_config(CAN1, 1U, &transmit_message);
        
        // 等待发送完成
        while(CAN_MB_TX_STATUS_DATA != can_mailbox_code_get(CAN1, 1U));
        
        // 翻转LED指示
        gd_eval_led_toggle(LED2);
    }
}
 
void cache_enable(void)
{
    SCB_EnableICache();
    SCB_EnableDCache();
}
 
// 重定向printf到USART
int fputc(int ch, FILE *f)
{
    usart_data_transmit(EVAL_COM, (uint8_t)ch);
    while(RESET == usart_flag_get(EVAL_COM, USART_FLAG_TBE));
    return ch;
}
 
// CAN1消息中断处理函数
void CAN1_Message_IRQHandler(void)
{
    if(SET == can_interrupt_flag_get(CAN1, CAN_INT_FLAG_MB0)) {
        can_interrupt_flag_clear(CAN1, CAN_INT_FLAG_MB0);
        can1_receive_flag = SET;
    }
}